package gui;

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.ItemEvent;
import java.awt.event.ItemListener;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;

import model.Model;

import javax.swing.AbstractAction;
import javax.swing.JFileChooser;
import javax.swing.JFrame;
import javax.swing.JSeparator;

import javax.swing.*;
import javax.swing.border.Border;
import javax.swing.border.CompoundBorder;
import javax.swing.border.EmptyBorder;
import javax.swing.border.EtchedBorder;
import javax.swing.border.TitledBorder;

/**
 * @author Troy Ferrell
 *
 */
public class PicassaGUI extends JFrame
{
	private static final long serialVersionUID = 1L;
	
	//**********************************************************************
	//
	// TODO: need to translate this all into resource file with manager
	//		 I know there are a lot of strings/digital values that are hardcoded in fuctions
	//		 Going to fix this with resources
	//
	//**********************************************************************
	
	private static final String PICTURE_FRAME_STR = "Picture Frame";
	private static final String PICASSO_BG_PATH = "src//resources//picassa.png";
	private static final String PICASSO_ICON_PATH = "src//resources//picassaIcon.png";
	
	// Model to interact with for system
	private Model myModel;
	
	// JFrame organizing picassa pictures
	private PictureFrame myPicFrame;
	
	// IO members
	private JTextField myExpressionField;
	private JTextArea myPromptField;
	
	// Properties members
	private JPanel myPropertiesPanel;
	private JList myVariableList;
	private JList myExpressionList;

	public PicassaGUI(Model newModel)
	{
		//Set JFrame parameters
		setModel(newModel);
		this.setTitle("PICASSA");
		this.setDefaultCloseOperation(EXIT_ON_CLOSE);
		this.setIconImage(new ImageIcon(PICASSO_ICON_PATH).getImage());
		
		createMenuBar();
		
		myPropertiesPanel = createProperties();
		this.getContentPane().add( myPropertiesPanel, BorderLayout.EAST);
		
		// Create Logo at center of background
		this.getContentPane().add(new JLabel(new ImageIcon(PICASSO_BG_PATH)), BorderLayout.CENTER);
		
		this.getContentPane().add( createIO(), BorderLayout.SOUTH);
		
		myPicFrame = new PictureFrame(PICTURE_FRAME_STR);
	}
	
	/**
	 * Create MenuBar for Picassa application
	 */
	public void createMenuBar()
	{
		JMenuBar myMenuBar = new JMenuBar();
		myMenuBar.add(makeFileMenu());
		myMenuBar.add(makeViewMenu());
		this.setJMenuBar(myMenuBar);
	}
	
	/**
	 * Create menu for menubar that deals with files(open,save,etc)
	 * 
	 * @return the File Menu
	 */
	public JMenu makeFileMenu()
	{
		JMenu fileMenu = new JMenu("File");
		fileMenu.add(new AbstractAction("Open")
        {
            public void actionPerformed (ActionEvent e)
            {
            	// TODO: Write code here to open new image
            }
        });
		fileMenu.add(new AbstractAction("Save")
        {
            public void actionPerformed (ActionEvent e)
            {
                  //TODO: Write code here to save image
            }
        });
		fileMenu.add(new JSeparator());
		fileMenu.add(new AbstractAction("Quit")
        {
            public void actionPerformed (ActionEvent e)
            {
                System.exit(0); // end program
            }
        });
		return fileMenu;
	}
	
	/**
	 * Create menu for menubar that deals with view and windows of application
	 * - hide/show windows
	 * - create new picture
	 * - refresh current picture
	 * 
	 * @return the View Menu
	 */
	public JMenu makeViewMenu()
	{
		JMenu viewMenu = new JMenu("View");
		
		JCheckBoxMenuItem pictureViewMenuItem = new JCheckBoxMenuItem("Picture Frame");
		pictureViewMenuItem.setSelected(true);
		viewMenu.add(pictureViewMenuItem);
		pictureViewMenuItem.addItemListener(new ItemListener(){
			public void itemStateChanged(ItemEvent e)
			{
				myPicFrame.setVisible(e.getStateChange() == ItemEvent.SELECTED);
			}
		});
		
		JCheckBoxMenuItem propertiesViewMenuItem = new JCheckBoxMenuItem("Properties");
		propertiesViewMenuItem.setSelected(true);
		viewMenu.add(propertiesViewMenuItem);
		propertiesViewMenuItem.addItemListener(new ItemListener(){
			public void itemStateChanged(ItemEvent e)
			{
				myPropertiesPanel.setVisible(e.getStateChange() == ItemEvent.SELECTED);
			}
		});
		
		viewMenu.add(new JSeparator());
		viewMenu.add(new AbstractAction("New Picture")
        {
            public void actionPerformed (ActionEvent e)
            {
            	myPicFrame.addNewTab(myPicFrame.NEW_IMAGE_STR);
            }
        });
		viewMenu.add(new AbstractAction("Refresh Picture")
        {
            public void actionPerformed (ActionEvent e)
            {
            	myPicFrame.repaint();
            }
        });

		return viewMenu;
	}

	/**
	 * Create the IO panel of the system. 
	 * Includes input elements for expressions 
	 * Includes output through prompt(JTextArea) for notifications about errors,exceptions, etc
	 * 
	 * @return the component containing IO components(in this case JPanel)
	 */
	public JComponent createIO()
	{
		JPanel IOPanel = new JPanel();
		IOPanel.setLayout(new BoxLayout(IOPanel, BoxLayout.Y_AXIS));
		 
		IOPanel.add( createExpressionPanel() );
		IOPanel.add( createPrompt() );
		
		return IOPanel;
	}
	
	/**
	 * Create input components for accepting expressions from user
	 * 
	 * @return Jpanel that holds expression components
	 */
	
	private JPanel createExpressionPanel()
	{
		JPanel expPanel = new JPanel();
		
		JLabel expLabel = new JLabel("Enter Expression:");
		
		myExpressionField = new JTextField();
		myExpressionField.setPreferredSize(new Dimension(500, 25));
		myExpressionField.addKeyListener(new KeyListener()
        {
            public void keyPressed (KeyEvent e) 
            {
            	if( e.getKeyCode() == KeyEvent.VK_ENTER)
            	{
            		myPicFrame.updateCurrentPicture( 
            				myModel.evaluate(myExpressionField.getText(), myPicFrame.getSize()) );
            	}
            	
            }
            public void keyReleased (KeyEvent e) {}
            public void keyTyped (KeyEvent e) {}
        });
		
		JButton enterButton = new JButton("Enter");
		enterButton.addActionListener(new ActionListener(){
			public void actionPerformed(ActionEvent e)
			{
				myPicFrame.updateCurrentPicture( 
						myModel.evaluate(myExpressionField.getText(), myPicFrame.getSize()) );
			}
		});
		
		expPanel.add(expLabel);
		expPanel.add(myExpressionField);
		expPanel.add(enterButton);
		
		return expPanel;
	}
	
	/**
	 * Create components for prompt of system
	 * 
	 * @return Container for prompt
	 */
	private JComponent createPrompt()
	{
		myPromptField = new JTextArea("PICASSA");
		myPromptField.setEditable(false);
		myPromptField.setBackground(Color.LIGHT_GRAY);
		myPromptField.setBorder(new EmptyBorder(10,10,10,10));
		
		JScrollPane promptScrollPane = new JScrollPane(myPromptField);
		promptScrollPane.setPreferredSize(new Dimension(100, 200));
		promptScrollPane.setBorder( BorderFactory.createTitledBorder( 
				BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), "PICASSA Prompt"));
		
		return promptScrollPane;
	}
	
	/**
	 * Create properties components for variables and expression lists
	 * 
	 * @return Container for property components
	 */
	public JPanel createProperties()
	{
		JPanel propertiesPanel = new JPanel();
		propertiesPanel.setLayout(new BoxLayout(propertiesPanel, BoxLayout.Y_AXIS));
		
		CompoundBorder cb = new CompoundBorder(BorderFactory.createTitledBorder( 
				BorderFactory.createLoweredBevelBorder(), "Properties"), new EmptyBorder(10,10,10,10));
		propertiesPanel.setBorder(cb);
		propertiesPanel.setPreferredSize(new Dimension(200, 100));
		
        myVariableList = createJList();
		JScrollPane myVariablePane = new JScrollPane(myVariableList);
		myVariablePane.setBorder( createListBorder("Variables" ));
		
		myExpressionList = createJList();
		JScrollPane myExpressionPane = new JScrollPane(myExpressionList);
		myExpressionPane.setBorder( createListBorder("Expressions") );
		
		propertiesPanel.add(myVariablePane);
		propertiesPanel.add(myExpressionPane);
		
		return propertiesPanel;
	}

	/**
	 * Create Border for scrollpanes that hold JLists of variables & expressions
	 * 
	 * @param the title for the border
	 * @return a titled border for lists
	 */
	private Border createListBorder(String title) 
	{
		TitledBorder expTitleBorder = BorderFactory.createTitledBorder( 
				BorderFactory.createEtchedBorder(EtchedBorder.LOWERED), title);
		expTitleBorder.setTitleJustification(TitledBorder.CENTER);
		return expTitleBorder;
	}

	/**
	 * Create a JList component 
	 * 
	 * @return the JList
	 */
	private JList createJList() 
	{
		JList returnList = new JList();// put data in here
		returnList.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
		returnList.setLayoutOrientation(JList.VERTICAL);
		returnList.setVisibleRowCount(-1); // show max possible
		
		return returnList;
	}
	
    /**
     * Updates current model for this view.
     */
    public void setModel (Model model)
    {
        if (model != null)
            myModel = model;
    }
    
    /**
     * Change size of picture frame if application size is changed
     */
    @Override
    public void setSize(int width, int height)
    {
    	myPicFrame.setSize(PictureFrame.NEW_IMG_WIDTH, PictureFrame.NEW_IMG_HEIGHT);
    	myPicFrame.setLocation(width/8, height/8);
    	super.setSize(width, height);
    }
    
    @Override
    public void setSize(Dimension d)
    {
    	this.setSize((int)d.getWidth(), (int)d.getHeight());
    }
    
    /**
     * Make sure to set picture frame visible when application 
     */
    @Override
    public void setVisible(boolean visible)
    {
    	super.setVisible(visible);
    	myPicFrame.setVisible(visible);
    }
    
	// add event handlers here***
}
